﻿using daonaite.core.Attribute;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;

namespace daonaite.core.DrawingCore
{
    /// <summary>
    /// 创建验证码
    /// </summary>
    [AutoLoad]
    public class CreateCode
    {
        private Random random = new Random();

       private string fontPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Font", "TAHOMA.TTF");

        SKSurface Surface;

        /// <summary>
        /// 图片宽度
        /// </summary>
        public int Width = 135;
        /// <summary>
        /// 图片高度
        /// </summary>
        public int Height = 40;
        /// <summary>
        /// 背景色
        /// </summary>
        private byte BackColorR = 185;
        /// <summary>
        /// 背景色
        /// </summary>
        private byte BackColorG = 185;
        /// <summary>
        /// 背景色
        /// </summary>
        private byte BackColorB = 185;
        /// <summary>
        /// 防靠色偏差值
        /// </summary>
        private byte BackOffset = 40;
        /// <summary>
        /// 字体大小
        /// </summary>
        private int TextSize = 30;
        /// <summary>
        /// 获取验证码
        /// </summary>
        /// <returns></returns>
        public (string, int) getcode()
        {
            int a = random.Next(1, 100);
            int b = random.Next(1, 100);
            string content = $"{a}+{b}=";
            int c = a + b;
            var info = new SKImageInfo(Width, Height);
            Surface = SKSurface.Create(info);

            Clear();
            WriteText(content);
            Confuse(4);
            var stream = GetImg();

            return (Convert.ToBase64String(stream), c);
        }

        /// <summary>
        /// 清除图像,保留背景色
        /// </summary>
        public void Clear()
        {
            var canvas = Surface.Canvas;
            canvas.Clear(new SKColor(BackColorR, BackColorG, BackColorB));
        }

        /// <summary>
        /// R限制范围
        /// </summary>
        public (byte begin, byte end, byte length) BoundsR
        {
            get
            {
                return Bounds(BackColorR);
            }
        }
        /// <summary>
        /// R限制范围
        /// </summary>
        public (byte begin, byte end, byte length) BoundsG
        {
            get
            {
                return Bounds(BackColorG);
            }
        }
        /// <summary>
        /// R限制范围
        /// </summary>
        public (byte begin, byte end, byte length) BoundsB
        {
            get
            {
                return Bounds(BackColorB);
            }
        }

        /// <summary>
        /// 颜色取值,限制范围
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        private (byte begin, byte end, byte length) Bounds(byte Value)
        {
            (byte begin, byte end, byte length) res = (0, 0, 0);

            res.begin = (byte)Math.Max(0, Value - BackOffset);
            res.end = (byte)Math.Min(255, Value + BackOffset);
            res.length = (byte)(res.end - res.begin);

            return res;
        }


        /// <summary>
        /// 写文字
        /// </summary>
        /// <param name="Text"></param>
        private void WriteText(string Text)
        {
            var canvas = Surface.Canvas;
            var xPoint = 6;///x点
            var yPoint = (Surface.Canvas.DeviceClipBounds.Height + TextSize) / 2; ///y点
            var paint = new SKPaint
            {
                Color = SKColors.Black,
                IsAntialias = true,
                Style = SKPaintStyle.Fill,
                TextAlign = SKTextAlign.Left,
                TextSize = TextSize,
                TextEncoding = SKTextEncoding.Utf8,
                Typeface = SKFontManager.Default.CreateTypeface(File.Open(fontPath,FileMode.Open)),
                StrokeWidth = 3
            };

            canvas.DrawText(Text, xPoint, yPoint, paint);

            //for (int i = 0; i < Text.Length; i++)
            //{
            //    // 偏移
            //    int xOffset = random.Next(-TextSize * 2 / 10, 1);///x偏移
            //    int yOffset = random.Next(-3, 3);///y偏移
            //    int angleOffset = random.Next(-15, 15);///角度偏移
            //    paint.Color = RandColoe();///随机颜色
            //    canvas.RotateDegrees(angleOffset, xPoint + xOffset, yPoint + yOffset);
            //    canvas.DrawText(Text[i].ToString(), xPoint + xOffset, yPoint + yOffset, paint);
            //    canvas.RotateDegrees(-angleOffset, xPoint + xOffset, yPoint + yOffset);
            //    xPoint = xPoint + TextSize + xOffset;
            //}

        }

        /// <summary>
        /// 混淆
        /// </summary>
        public void Confuse(uint Count)
        {
            var canvas = Surface.Canvas;
            for (int i = 0; i < Count; i++)
            {
                int x = random.Next(0, canvas.DeviceClipBounds.Width);
                int y = random.Next(0, canvas.DeviceClipBounds.Height);
                int radius = random.Next(TextSize, TextSize * 2);

                var paint = new SKPaint
                {
                    Color = RandColoe(),///随机颜色
                    IsAntialias = true,
                    Style = SKPaintStyle.Stroke,
                    TextAlign = SKTextAlign.Left,
                    TextSize = TextSize,
                    TextEncoding = SKTextEncoding.Utf8,
                    StrokeWidth = 1
                };
                canvas.DrawCircle(x, y, radius, paint);
            }

        }

        /// <summary>
        /// 生成和背景具有区分的随机颜色
        /// </summary>
        /// <returns></returns>
        private SKColor RandColoe()
        {
            var r = random.Next(0, 255 - BoundsR.length);
            if (r > BoundsR.begin && r < BoundsR.end)
            {
                r = (r + BoundsR.length) % 256;
            }
            var g = (r + random.Next(50, 190)) % 256;
            if (g > BoundsG.begin && g < BoundsG.end)
            {
                g = (g + BoundsG.length) % 256;
            }
            var b = (g + random.Next(50, 190)) % 256;
            if (b > BoundsB.begin && b < BoundsB.end)
            {
                b = (b + BoundsB.length) % 256;
            }
            return new SKColor((byte)r, (byte)g, (byte)b);
        }

        /// <summary>
        /// 获取图片流,png格式
        /// </summary>
        /// <returns></returns>
        public byte[] GetImg()
        {
            using (var image = Surface.Snapshot())
            using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
            {
                return data.ToArray();
            }
        }
    }
}
